package com.etocrm.saas.lib.base.log.requestlog.advice;

import cn.hutool.core.io.IoUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

/**
 * 打印日志的log , 
 * 缺点:
 * 1. 只能在interceptor放行通过后才可以打印日志.
 * 2. 只能打印请求正确的参数
 * 3. 只能打印 application/json 的日志
 * Created by Xs on 2022/12/14.
 */
@Slf4j
@ControllerAdvice
public class HttpLogAdvice extends RequestBodyAdviceAdapter {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        if (converterType.equals(MappingJackson2HttpMessageConverter.class)) {
            inputMessage.getBody().mark(0);
            log.info("请求地址 : {} ; 请求头 : {}  ;\n 请求参数 : {}", request.getRequestURI(), objectMapper.writeValueAsString(inputMessage.getHeaders()), IoUtil.read(inputMessage.getBody(), StandardCharsets.UTF_8));
            inputMessage.getBody().reset();
            return inputMessage;
        } else {
            String queryString = request.getQueryString();
            log.info("请求地址 : {} ; 请求头 : {}  ;\n  queryString : {}, paramMap : {}", request.getRequestURI(), objectMapper.writeValueAsString(inputMessage.getHeaders()), queryString, objectMapper.writeValueAsString(request.getParameterMap()));
        }

        return inputMessage;
    }
}
